#pragma once
#include <sw/redis++/redis.h>
class RedisClientFactory {
public:
    static std::shared_ptr<sw::redis::Redis> create(const std::string& ip, int port, int db, bool keep_alive = true) {
        sw::redis::ConnectionOptions options;
        options.host = ip;
        options.port = port;
        options.db = db;
        options.keep_alive = keep_alive;
        return std::make_shared<sw::redis::Redis>(options);
    }
};


class Session {
public:
    using ptr = std::shared_ptr<Session>;
    Session(const std::shared_ptr<sw::redis::Redis>& redis_client)
        : _redis_client(redis_client) {}
    bool append(const std::string& session_id, const std::string& user_id) {
        bool success = _redis_client->set(session_id, user_id);
        if (!success) {
            return false;
        }
        return true;
    }

    bool remove(const std::string& session_id) {
        auto result = _redis_client->del(session_id);
        return result > 0;
    }

    sw::redis::OptionalString user_id(const std::string& session_id) {
        return _redis_client->get(session_id);
    }
private:
    std::shared_ptr<sw::redis::Redis> _redis_client;    
};


class Status {
public:
    using ptr = std::shared_ptr<Status>;
    Status(const std::shared_ptr<sw::redis::Redis>& redis_client)
        : _redis_client(redis_client) {}

    bool append(const std::string& user_id) {
        bool success = _redis_client->set(user_id, "");
        if (!success) {
            return false;
        }
        return true;
    }

    bool remove(const std::string& user_id) {
        auto result = _redis_client->del(user_id);
        return result > 0;
    }

    bool exists(const std::string& user_id) {
        auto ret = _redis_client->get(user_id);
        if(ret)
            return true;
        return false;
    }
private:
    std::shared_ptr<sw::redis::Redis> _redis_client;
};


class Codes {
public:
    using ptr = std::shared_ptr<Codes>;
    Codes(const std::shared_ptr<sw::redis::Redis>& redis_client)
        : _redis_client(redis_client) {}

    bool append(const std::string& code_id, const std::string& code, 
                std::chrono::milliseconds expire_time = std::chrono::milliseconds(300000)) {
        bool success = _redis_client->set(code_id, code, expire_time);
        if (!success) {
            return false;
        }
        return true;
    }
    bool remove(const std::string& code_id) {
        auto result = _redis_client->del(code_id);
        return result > 0;
    }
    sw::redis::OptionalString code(const std::string& code_id) {
        return _redis_client->get(code_id);
    }

private:
    std::shared_ptr<sw::redis::Redis> _redis_client;
};